namespace BizTalk.PipelineComponents 
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.BizTalk.ExplorerOM;
    using Microsoft.Win32;
    using System.Globalization;
    using System.Xml;
    using System.IO;

    public class BTSSchemaResolver : System.Xml.XmlUrlResolver {
        private static BtsCatalogExplorer btsCatalog;

        static BTSSchemaResolver() {
            btsCatalog = new BtsCatalogExplorer();
            btsCatalog.ConnectionString = GetBizTalkManagementConnectionString();
        }

        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) {
            if (absoluteUri.Scheme == "bts")
            {
                // We know for sure that in this case this uri has the format
                // bts://<Schema Name>
                string schemaName = absoluteUri.OriginalString.Substring(6);
                MemoryStream m = new MemoryStream();
                using (StringReader sr = new StringReader(btsCatalog.Schemas[schemaName].XmlContent)) {
                    byte[] buffer = Encoding.Unicode.GetBytes(sr.ReadToEnd());
                    m.Write(buffer, 0, buffer.Length);
                    m.Flush();
                    m.Seek(0, SeekOrigin.Begin);
                }
                return m;
            }
            // Either file or http scheme
            return base.GetEntity(absoluteUri, role, ofObjectToReturn);
        }

        public override Uri ResolveUri(Uri baseUri, string relativeUri) {
            Uri resolvedUri = base.ResolveUri(baseUri, relativeUri);
            try {
                if (btsCatalog.Schemas[relativeUri] != null) {
                    resolvedUri = new Uri("bts://" + relativeUri);
                }
            } catch (Exception) {
                // slallow exceptions and return unchanged uri
            }
            return resolvedUri;

        }

        #region Utilities
        
        private static string GetFileFragmentFromUri(Uri absoluteUri) {
            string origString = absoluteUri.OriginalString;
            int start = origString.LastIndexOf("\\") + 1;
            string name = origString.Substring(start);
            return name;
        }

        private static string GetBizTalkManagementConnectionString() {
            string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\BizTalk Server\3.0\Administration";
            string valueName = "MgmtDBServer";
            string str3 = "MgmtDBName";
            object obj2 = Registry.GetValue(keyName, valueName, null);
            object obj3 = Registry.GetValue(keyName, str3, null);
            if ((obj2 == null) || (obj3 == null)) {
                throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "Could not establish name of server and/or database hosting BizTalk Management database (BizTalkMgmtDb). (Should be stored at \"{0}\" and \"{1}\" beneath \"{2}\".)", valueName, str3, keyName));
            }
            return string.Format(CultureInfo.CurrentCulture, "Data Source=\"{0}\";Initial Catalog=\"{1}\";Integrated Security=SSPI", new object[] { obj2, obj3 });
        } 
        #endregion
        
    }
}
